package com.zhl.study.util;

import org.apache.commons.jexl3.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;

/**
 * 计算工具
 */
public class CalculateKit {

    /**
     * 公式计算
     * @param formula       公式
     * @param variables     带人公式的参数以及参数值
     * @return
     */
    public static BigDecimal calculateFormula(String formula, Map<String, BigDecimal> variables) {

        JexlEngine jexl = new JexlBuilder()
                .namespaces(Map.of("math", Math.class)) // 将 Math 类绑定到 math 命名空间
                .create();

        // 去除公式中的多余空格（可扩展处理特殊字符）
        formula = preprocessFormula(formula);

        // 创建表达式
        JexlExpression expression = jexl.createExpression(formula);

        // 创建上下文，将变量值注入
        JexlContext context = new MapContext();
        for (Map.Entry<String, BigDecimal> entry : variables.entrySet()) {
            context.set(entry.getKey(), entry.getValue());
        }

        // 计算公式结果
        Object result = expression.evaluate(context);

        // 确保结果以 BigDecimal 返回
        if (result instanceof Number) {
            return new BigDecimal(result.toString());
        } else {
            throw new IllegalArgumentException("无法计算公式：" + formula);
        }
    }

    /**
     * 去除公式空格
     * @param formula
     * @return
     */
    public static String preprocessFormula(String formula) {
        // 去除多余空格
        formula = formula.replaceAll("\\s+", "")
        .replaceAll("\\^", "**");
        return formula;
    }

    /**
     * 获取指定类型的数字的BigDecimal类型保留三位小数，只取前三位，第四位开始直接忽略不做四舍五入
     * @param strNumber 字符串类型的数字
     * @return BigDecimal
     */
    public static BigDecimal getBigDecimal(String strNumber) {
        if (strNumber == null || strNumber.isEmpty()) {
            throw new IllegalArgumentException("输入数字不能为空");
        }
        return new BigDecimal(strNumber).setScale(3, RoundingMode.DOWN);
    }

    public static BigDecimal getBigDecimal(int number) {
        return BigDecimal.valueOf(number).setScale(3, RoundingMode.DOWN);
    }

    public static BigDecimal getBigDecimal(long number) {
        return BigDecimal.valueOf(number).setScale(3, RoundingMode.DOWN);
    }

    public static BigDecimal getBigDecimal(double number) {
        return BigDecimal.valueOf(number).setScale(3, RoundingMode.DOWN);
    }

    public static BigDecimal getBigDecimal(float number) {
        return BigDecimal.valueOf(number).setScale(3, RoundingMode.DOWN);
    }

    /**
     * 除法计算，只取前三位，第四位开始直接忽略不做四舍五入
     * @param dividend 被除数
     * @param divisor 除数
     * @param scale 小数点保留位数
     * @return BigDecimal
     */
    public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor, int scale) {
        if (divisor == null || BigDecimal.ZERO.compareTo(divisor) == 0) {
            throw new ArithmeticException("除数不能为零");
        }
        if (scale < 0) {
            throw new IllegalArgumentException("保留的小数位数不能为负数");
        }
        return dividend.divide(divisor, scale, RoundingMode.DOWN);
    }

    /**
     * 除以1000保留三位小数不做四舍五入
     * @param dividend
     * @return
     */
    public static BigDecimal divideOneThousandKeepThree(BigDecimal dividend) {
        return divide(dividend, new BigDecimal(1000), 3);
    }
}
